package com.lwphk.easydocs.core;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;

import com.lwphk.easydocs.annotations.Doc;
import com.lwphk.easydocs.annotations.DocMethod;
import com.lwphk.easydocs.annotations.DocNil;
import com.lwphk.easydocs.core.vo.ControllerInfo;
import com.lwphk.easydocs.core.vo.DocsBasicInfo;
import com.lwphk.easydocs.core.vo.MethodInfo;

/**
 * 解析RequestMapping
 * @author liwenping
 *
 */
public class ParseRequestMapping {

	
	private static final Logger log = LoggerFactory.getLogger(ParseRequestMapping.class);
	
	ParseParameterAdapter parseParameterHandler = new ParseParameterAdapter();
	
	public void parseBasicInfo(Map<RequestMappingInfo, HandlerMethod> map) {
		log.info("开始解析接口");

		Set<RequestMappingInfo> requestMappingInfos = map.keySet();
		
		for (RequestMappingInfo requestMappingInfo : requestMappingInfos) {
			HandlerMethod handlerMethod = map.get(requestMappingInfo);
			Class<?> clazz = handlerMethod.getBeanType();
			Method method = handlerMethod.getMethod();
			if(skipParseController(clazz)) { 
				continue;
			}
			
			
			ControllerInfo  cInfo = parseController(clazz);
			
			MethodInfo mi = parseMethod(cInfo,method, requestMappingInfo);
			
			parseParameterHandler.parseParameter(method, mi);
			

			cInfo.getMethodInfos().add(mi);

		}

		log.info("接口解析完成");
	}
	
	
	
	
	
	
	private MethodInfo parseMethod(ControllerInfo  cInfo,Method method,RequestMappingInfo requestMappingInfo) {
		Map<String, String> fieldMap = DocsBasicInfo.GlobalFieldMappingMap;
		MethodInfo mi = new MethodInfo();
		mi.setTags(method.getName());
		mi.setParentDir(cInfo.getDir());
		mi.setMethodName(method.getName());
		mi.setReturnType(method.getReturnType());
		mi.setPatterns(requestMappingInfo.getPatternsCondition().getPatterns());
		
		Set<String> requestMethodSet = requestMappingInfo.getMethodsCondition().getMethods().stream().map(e->e.name()).collect(Collectors.toSet());
		if(!requestMethodSet.isEmpty()) {
			mi.setRequestMethods(requestMethodSet);
		}
			
		
		DocMethod dm = method.getAnnotation(DocMethod.class);
		if(dm != null) {
			mi.setRemark(dm.remark());
			mi.setTags(dm.name());
		}else {
			if(StringUtils.isNotBlank(fieldMap.get(mi.getMethodName()))) {
				mi.setTags(fieldMap.get(mi.getMethodName()));
			}
		}
		
		return mi;
	}
	
	
	/**
	 * 解析控制器信息
	 * @param clazz
	 * @return
	 */
	private ControllerInfo parseController(Class<?> clazz) {
		Map<String, ControllerInfo> controllerInfoMap = DocsBasicInfo.ControllerInfoMap;
		Map<String, String> fieldMap = DocsBasicInfo.GlobalFieldMappingMap;
		String key = clazz.getName();
		ControllerInfo info = controllerInfoMap.get(key);
		if (info == null) {
			info = new ControllerInfo();
			info.setClazz(clazz);
			info.setName(clazz.getName());
			info.setSimpleName(clazz.getSimpleName());
			info.setDir(clazz.getSimpleName());
			
			Doc doc = clazz.getAnnotation(Doc.class);
			if (doc != null) {
				info.setDir(doc.dir());
				info.setRemark(doc.remark());
			} else {
				String simpleName = info.getSimpleName();
				if(StringUtils.isNotBlank(fieldMap.get(simpleName))) {
					info.setDir(fieldMap.get(simpleName));
				}
				
			}
			controllerInfoMap.put(key, info);
		}
		
		return info;
	}

	
	
	/**
	 * 过滤不需要的控制器
	 * @param clazz
	 * @return
	 */
	public boolean skipParseController(Class<?> clazz) {
		boolean skip = false;
		if (clazz.getAnnotation(DocNil.class) != null) {
			skip = true;
		}else if(clazz.getName().startsWith("com.lwphk.easydocs")) {
			skip = true;
		}else if(clazz.getName().startsWith("org.springframework.boot.autoconfigure")) {
			skip = true;
		}
		return skip;
	}
	
	
}
